package com.example.cas;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

@Slf4j
public class ABADemo {
    static AtomicInteger atomicInteger = new AtomicInteger(100);
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);

    public static void main(String[] args) {
//        abaProblem();
        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            log.info("默认版本号: {}", stamp);
            //让后面的t4获得和t3一样的版本号，都是1，好比较
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                log.error("Exception", e.fillInStackTrace());
            }

            atomicStampedReference.compareAndSet(100, 101, stamp, stamp + 1);
            log.info("---1次版本号: {}", atomicStampedReference.getStamp());
            atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);
            log.info("---2次版本号: {}", atomicStampedReference.getStamp());
        }, "t3").start();

        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            log.info("---默认版本号: {}", stamp);
            //上前面的t3完成ABA问题
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                log.error("Exception", e.fillInStackTrace());
            }
            boolean result = atomicStampedReference.compareAndSet(100, 20210308, stamp,
                    stamp + 1);
            log.info("---操作成功否：{},{},{}", result, atomicStampedReference.getStamp(), atomicStampedReference.getReference());
        }, "t4").start();
    }

    public static void abaProblem() {
        new Thread(() -> {
            atomicInteger.compareAndSet(100, 101);
            atomicInteger.compareAndSet(101, 100);
        }, "t1").start();

        //暂停毫秒
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            log.error("Exception", e.fillInStackTrace());
        }

        new Thread(() -> {
            boolean b = atomicInteger.compareAndSet(100, 20210308);
            log.info("ret：{},{}", b, atomicInteger.get());
        }, "t2").start();
    }
}
